//
//  GameModel.cpp
//  NinjaTurtle
//
//  Created by Nguyen Tri Chung on 1/8/15.
//
//

#include "GameModel.h"

static GameModel* gameModelInstance = NULL;

GameModel* GameModel::getInstance() {
    if (gameModelInstance == NULL) {
        gameModelInstance = new GameModel();
        CC_SAFE_RETAIN(gameModelInstance);
    }
    return gameModelInstance;
}

GameModel::GameModel() {
    this->currentLevel = NULL;
    this->gameState = GS_WAIT;
    this->level = -1;
    this->currentDelayToTransit = -1;
    this->currentDelayToNextMap = -1;
    this->savedData = NULL;
    this->numberDead = 0;
    this->loadData();
    Director::getInstance()->getScheduler()->scheduleUpdate(this, SCHEDULE_GAME_MODEL, false);
}

GameModel::~GameModel() {
    CC_SAFE_RELEASE(this->currentLevel);
    CC_SAFE_RELEASE(this->savedData);
}

void GameModel::loadData() {
    this->savedData = new SavedData();
    CC_SAFE_RETAIN(this->savedData);
    {
        string fileData = CStringUtil::readFile(DOC_USER, true, false, true);
        if (fileData == "") {
            fileData = CStringUtil::readFile(DOC_USER, false, true, true);
        }
        if (fileData != "") {
            vector<string> values = CStringUtil::split(fileData, '$');
            for (int i = 0; i < values.size(); i++) {
                string text = values.at(i);
                
                if (i == 0) {
                    int levelInt = atoi(text.data());
                    this->savedData->setLevel(levelInt);
                } else if (i == 1) {
                    int musicInt = atoi(text.data());
                    this->savedData->setMusicOn(musicInt == 1 ? true : false);
                } else if (i == 2) {
                    int effectInt = atoi(text.data());
                    this->savedData->setEffectOn(effectInt == 1 ? true : false);
                }
            }
        }
    }
}

void GameModel::play(int level) {
    this->level = level;
    this->gameState = GS_LOAD;
    
    this->currentLevel = new Level(level);
    CC_SAFE_RETAIN(this->currentLevel);
    
    this->currentLevel->loadMap();
    this->currentLevel->updateViewPoint();
    
    GameEvent* startGameEvent = new GameEvent();
    startGameEvent->setEventCode(EVT_MAP_CREATED);
    this->fireEvent(startGameEvent);
}

void GameModel::next() {
    if (this->currentLevel != NULL) {
        CC_SAFE_RELEASE(this->currentLevel);
        this->currentLevel = NULL;
    }
    this->numberDead++;
    this->level = this->level + 1;
    this->play(this->level);
}

bool GameModel::isLastMap() {
    if (this->level >= CONFIG_TOTAL_LEVELS) {
        return true;
    }
    return false;
}

void GameModel::quit() {
    if (this->currentLevel != NULL) {
        CC_SAFE_RELEASE(this->currentLevel);
        this->currentLevel = NULL;
    }
    this->gameState = GS_WAIT;
}

void GameModel::pause() {
    this->gameState = GS_PAUSE;
}

void GameModel::resume() {
    this->gameState = GS_PLAY;
}

void GameModel::replay() {
    if (this->currentLevel != NULL) {
        CC_SAFE_RELEASE(this->currentLevel);
        this->currentLevel = NULL;
    }
    this->numberDead++;
    this->play(this->level);
}

void GameModel::transit(float time) {
    this->currentDelayToTransit = time;
}

void GameModel::update(float dt) {
    SimpleAudioEngine* soundModel = SimpleAudioEngine::getInstance();
    if (soundModel != NULL) {
        if (this->savedData->getMusicOn()) {
            soundModel->setBackgroundMusicVolume(CONFIG_MAX_VOLUME_MUSIC);
        } else {
            soundModel->setBackgroundMusicVolume(0);
        }
        
        if (this->savedData->getEffectOn()) {
            soundModel->setEffectsVolume(CONFIG_MAX_VOLUME_EFFECT);
        } else {
            soundModel->setEffectsVolume(0);
        }
    }

    if (this->gameState == GS_LOAD) {
        this->currentDelayToTransit -= dt;
        if (this->currentDelayToTransit < 0) {
            this->gameState = GS_PLAY;
        }
    }
    
    if (this->gameState == GS_PLAY) {
        this->currentLevel->update(dt);
        
        if (this->currentLevel->getTurtle()->getDead()) {
            this->gameState = GS_REPLAY;
            this->currentDelayToNextMap = CONFIG_DELAY_TO_NEXT_MAP;
            
            GameEvent* gameEvent = new GameEvent();
            gameEvent->setEventCode(EVT_TURTLE_DIE);
            this->fireEvent(gameEvent);
        }
        
        if (this->currentLevel->getTurtle()->getDisappear()) {
            this->gameState = GS_FINISH;
            this->currentDelayToNextMap = CONFIG_DELAY_TO_NEXT_MAP;
            
            GameEvent* gameEvent = new GameEvent();
            gameEvent->setEventCode(EVT_TURTLE_PASS);
            this->fireEvent(gameEvent);
        }
    }
    
    if (this->gameState == GS_REPLAY) {
        this->currentLevel->update(dt);
        this->currentDelayToNextMap -= dt;
        if (this->currentDelayToNextMap < 0) {
            GameEvent* startGameEvent = new GameEvent();
            startGameEvent->setEventCode(EVT_REPLAY_MAP);
            this->fireEvent(startGameEvent);
        }
    }
    
    if (this->gameState == GS_FINISH) {
        this->currentLevel->update(dt);
        this->currentDelayToNextMap -= dt;
        if (this->currentDelayToNextMap < 0) {
            GameEvent* startGameEvent = new GameEvent();
            startGameEvent->setEventCode(EVT_NEXT_MAP);
            this->fireEvent(startGameEvent);
        }
    }
}

void GameModel::save() {
    char savedText[200];
    int level = this->savedData->getLevel();
    int musicOn = this->savedData->getMusicOn() ? 1 : 0;
    int effectOn = this->savedData->getEffectOn() ? 1 : 0;
    sprintf(savedText, TXT_SAVED_TEXT, level, musicOn, effectOn);
    CStringUtil::writeFile(savedText, DOC_USER, true);
}

void GameModel::updateLevel() {
    if (this->level > this->savedData->getLevel()) {
        this->savedData->setLevel(this->level);
    }
}
